﻿// Decompiled with JetBrains decompiler
// Type: System.Web.Razor.Text.TextChange
// Assembly: System.Web.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
// MVID: 682513D6-F37E-48AC-9909-F3EE103CFF14
// Assembly location: D:\Project\Idea\无人机外网\uav\客户端工程\排查工具\bin\Release\System.Web.Razor.dll

using Microsoft.Internal.Web.Utils;
using System.Globalization;
using System.Text;
using System.Web.Razor.Parser.SyntaxTree;

namespace System.Web.Razor.Text
{
  /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code.Describes a text change operation.</summary>
  public struct TextChange
  {
    private string _newText;
    private string _oldText;

    internal TextChange(
      int position,
      int oldLength,
      ITextBuffer oldBuffer,
      int newLength,
      ITextBuffer newBuffer)
      : this(position, oldLength, oldBuffer, position, newLength, newBuffer)
    {
    }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code.Initializes a new instance of the <see cref="T:System.Web.Razor.Text.TextChange" /> class.</summary>
    /// <param name="oldPosition">The position of the text change in the snapshot immediately before the change.</param>
    /// <param name="oldLength">The length of the old text.</param>
    /// <param name="oldBuffer">An old text buffer.</param>
    /// <param name="newPosition">The position of the text change in the snapshot immediately after the change.</param>
    /// <param name="newLength">The length of the new text.</param>
    /// <param name="newBuffer">A new text buffer.</param>
    public TextChange(
      int oldPosition,
      int oldLength,
      ITextBuffer oldBuffer,
      int newPosition,
      int newLength,
      ITextBuffer newBuffer)
      : this()
    {
      if (oldPosition < 0)
        throw new ArgumentOutOfRangeException(nameof (oldPosition), string.Format((IFormatProvider) CultureInfo.CurrentCulture, CommonResources.Argument_Must_Be_GreaterThanOrEqualTo, (object) "0"));
      if (newPosition < 0)
        throw new ArgumentOutOfRangeException(nameof (newPosition), string.Format((IFormatProvider) CultureInfo.CurrentCulture, CommonResources.Argument_Must_Be_GreaterThanOrEqualTo, (object) "0"));
      if (oldLength < 0)
        throw new ArgumentOutOfRangeException(nameof (oldLength), string.Format((IFormatProvider) CultureInfo.CurrentCulture, CommonResources.Argument_Must_Be_GreaterThanOrEqualTo, (object) "0"));
      if (newLength < 0)
        throw new ArgumentOutOfRangeException(nameof (newLength), string.Format((IFormatProvider) CultureInfo.CurrentCulture, CommonResources.Argument_Must_Be_GreaterThanOrEqualTo, (object) "0"));
      if (oldBuffer == null)
        throw new ArgumentNullException(nameof (oldBuffer));
      if (newBuffer == null)
        throw new ArgumentNullException(nameof (newBuffer));
      this.OldPosition = oldPosition;
      this.NewPosition = newPosition;
      this.OldLength = oldLength;
      this.NewLength = newLength;
      this.NewBuffer = newBuffer;
      this.OldBuffer = oldBuffer;
    }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code.Gets or sets the position of the text change in the snapshot immediately before the change.</summary>
    /// <returns>The position of the text change in the snapshot immediately before the change.</returns>
    public int OldPosition { get; private set; }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code.Gets or sets the position of the text change in the snapshot immediately after the change.</summary>
    /// <returns>The position of the text change in the snapshot immediately after the change.</returns>
    public int NewPosition { get; private set; }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code.Gets or sets the length of the old text.</summary>
    /// <returns>The length of the old text.</returns>
    public int OldLength { get; private set; }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code.Gets or sets the length of the new text.</summary>
    /// <returns>The length of the new text.</returns>
    public int NewLength { get; private set; }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code.Gets or sets a new text buffer.</summary>
    /// <returns>A new text buffer.</returns>
    public ITextBuffer NewBuffer { get; private set; }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code.Gets or sets an old text buffer.</summary>
    /// <returns>An old text buffer.</returns>
    public ITextBuffer OldBuffer { get; private set; }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code.Gets or sets the text that was replaced.</summary>
    /// <returns>The text that was replaced.</returns>
    public string OldText
    {
      get
      {
        if (this._oldText == null && this.OldBuffer != null)
          this._oldText = TextChange.GetText(this.OldBuffer, this.OldPosition, this.OldLength);
        return this._oldText;
      }
    }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code.Gets or sets the text that replaced the old text.</summary>
    /// <returns>The text that replaced the old text.</returns>
    public string NewText
    {
      get
      {
        if (this._newText == null)
          this._newText = TextChange.GetText(this.NewBuffer, this.NewPosition, this.NewLength);
        return this._newText;
      }
    }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code.Gets a value that indicates whether this text change is an insert.</summary>
    /// <returns>true if this text change is an insert; otherwise, false.</returns>
    public bool IsInsert => this.OldLength == 0 && this.NewLength > 0;

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code.Gets a value that indicates whether this text change is a delete.</summary>
    /// <returns>true if this text change is a delete; otherwise, false.</returns>
    public bool IsDelete => this.OldLength > 0 && this.NewLength == 0;

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code.Gets a value that indicates whether this text change is a replace.</summary>
    /// <returns>true if this text change is a replace; otherwise, false.</returns>
    public bool IsReplace => this.OldLength > 0 && this.NewLength > 0;

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code.Determines whether the specified object is equal to the current object.</summary>
    /// <returns>true if the specified object is equal to the current object; otherwise, false.</returns>
    /// <param name="obj">The object to compare to.</param>
    public override bool Equals(object obj) => obj is TextChange textChange && textChange.OldPosition == this.OldPosition && (textChange.NewPosition == this.NewPosition && textChange.OldLength == this.OldLength) && (textChange.NewLength == this.NewLength && this.OldBuffer.Equals((object) textChange.OldBuffer)) && this.NewBuffer.Equals((object) textChange.NewBuffer);

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code.Applies the specified text change.</summary>
    /// <returns>A string that contains the value of the text.</returns>
    /// <param name="content">The content of the text.</param>
    /// <param name="changeOffset">The change offset.</param>
    public string ApplyChange(string content, int changeOffset)
    {
      int startIndex = this.OldPosition - changeOffset;
      return content.Remove(startIndex, this.OldLength).Insert(startIndex, this.NewText);
    }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code.Applies the specified text change.</summary>
    /// <returns>A string that contains the value of the text.</returns>
    /// <param name="span">The span of the text change.</param>
    public string ApplyChange(Span span) => this.ApplyChange(span.Content, span.Start.AbsoluteIndex);

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code.Gets the hash code for this text change.</summary>
    /// <returns>The hash code for this text change.</returns>
    public override int GetHashCode() => this.OldPosition ^ this.NewPosition ^ this.OldLength ^ this.NewLength ^ this.NewBuffer.GetHashCode() ^ this.OldBuffer.GetHashCode();

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code.Returns a string representation of the text change.</summary>
    /// <returns>A string representation of the text change.</returns>
    public override string ToString() => string.Format((IFormatProvider) CultureInfo.CurrentCulture, "({0}:{1}) \"{3}\" -> ({0}:{2}) \"{4}\"", (object) this.OldPosition, (object) this.OldLength, (object) this.NewLength, (object) this.OldText, (object) this.NewText);

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code.Returns a normalized value of this text change.</summary>
    /// <returns>A normalized value of this text change.</returns>
    public TextChange Normalize() => this.OldBuffer != null && this.IsReplace && (this.NewLength > this.OldLength && this.NewText.StartsWith(this.OldText, StringComparison.Ordinal)) && this.NewPosition == this.OldPosition ? new TextChange(this.OldPosition + this.OldLength, 0, this.OldBuffer, this.OldPosition + this.OldLength, this.NewLength - this.OldLength, this.NewBuffer) : this;

    private static string GetText(ITextBuffer buffer, int position, int length)
    {
      if (length == 0)
        return string.Empty;
      int position1 = buffer.Position;
      try
      {
        buffer.Position = position;
        if (length == 1)
          return ((char) buffer.Read()).ToString();
        StringBuilder stringBuilder = new StringBuilder();
        for (int index = 0; index < length; ++index)
        {
          char c = (char) buffer.Read();
          stringBuilder.Append(c);
          if (char.IsHighSurrogate(c))
            stringBuilder.Append((char) buffer.Read());
        }
        return stringBuilder.ToString();
      }
      finally
      {
        buffer.Position = position1;
      }
    }

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code.Determines whether the two text change are equal.</summary>
    /// <returns>true if the two text change are equal; otherwise, false.</returns>
    /// <param name="left">The left text change.</param>
    /// <param name="right">The right text change.</param>
    public static bool operator ==(TextChange left, TextChange right) => left.Equals((object) right);

    /// <summary>This type/member supports the .NET Framework infrastructure and is not intended to be used directly from your code.Determines whether the two text change are not equal.</summary>
    /// <returns>true if the two text change are not equal; otherwise, false.</returns>
    /// <param name="left">The left text change.</param>
    /// <param name="right">The right text change.</param>
    public static bool operator !=(TextChange left, TextChange right) => !left.Equals((object) right);
  }
}
